/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stdint.h"
#include <string.h>
#include "tx_api.h"
#include "common.h"
#include "os_obj.h"

/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Variables -----------------------------------------------------------------*/

/* USER CODE BEGIN Variables */
//CHAR  _tx_version_id[100] =  "Copyright (c) Microsoft Corporation. All rights reserved.  * ThreadX 6.1";
/* USER CODE END Variables */

/* Function prototypes -------------------------------------------------------*/

/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

/* Hook prototypes */

/* USER CODE BEGIN Application */


/**
* @brief  Start the RTOS Kernel with executing the specified thread.
* @param  thread_def    thread definition referenced with \ref osThread.
* @param  argument      pointer that is passed to the thread function as start argument.
* @retval status code that indicates the execution status of the function
* @note   MUST REMAIN UNCHANGED: \b osKernelStart shall be consistent in every CMSIS-RTOS.
*/
osStatus osKernelStart (void)
{
    //os entry
    tx_kernel_enter();
    
    return osOK;
}

/*********************** Thread Management *****************************/
/**
* @brief  Create a thread and add it to Active Threads and set it to state READY.
* @param  thread_def    thread definition referenced with \ref osThread.
* @param  argument      pointer that is passed to the thread function as start argument.
* @retval thread ID for reference by other functions or NULL in case of error.
* @note   MUST REMAIN UNCHANGED: \b osThreadCreate shall be consistent in every CMSIS-RTOS.
*/
osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument)
{
    void (*fun)(ULONG);
    UINT os_err;
    
    fun = ( void (*)(ULONG) ) thread_def->pthread;

    os_err = tx_thread_create(  thread_def->controlblock,    //task tcb 
                       thread_def->name,            //task name
                       fun,                         //task entry
                       (ULONG)argument,             //task argv
                       thread_def->buffer,          //task stack
                       thread_def->stacksize,       //stack size 
                       thread_def->tpriority,       //task priority
                       thread_def->tpriority,       //priority force sw
                       TX_NO_TIME_SLICE,            //time slice off
                       TX_AUTO_START);              //auto start

    os_api_exe_check();
    
    if(os_err)
    {
      dbg_print("creat thread fail : %s \n", thread_def->name);
    }
    else
    {
      dbg_print("creat thread ok : %32s , prio : %d\n", 
                thread_def->name, 
                thread_def->tpriority);
    }
    
    return thread_def->controlblock;
}

/*********************** Generic Wait Functions *******************************/
/**
* @brief   Wait for Timeout (Time Delay)
* @param   millisec      time delay value
* @retval  status code that indicates the execution status of the function.
*/
osStatus osDelay (uint32_t millisec)
{
    UINT os_err;
    
    os_err = tx_thread_sleep(millisec);
    
    (void)os_err;

    os_api_exe_check();
    
    return osOK;
}

/*******************   Message Queue Management Functions  *********************/

/**
* @brief Create and Initialize a Message Queue
* @param queue_def     queue definition referenced with \ref osMessageQ.
* @param  thread_id     thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
* @retval  message queue ID for reference by other functions or NULL in case of error.
* @note   MUST REMAIN UNCHANGED: \b osMessageCreate shall be consistent in every CMSIS-RTOS.
*/
osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id)
{
    /* creat quene */
    tx_queue_create(queue_def->controlblock,                            //Pointer to queue control block
                    queue_def->name,                                    //Pointer to queue name
                    1,                                                  //Size of each queue message (Number of ULONG)
                    queue_def->buffer,                                  //Starting address of the queue area
                    queue_def->queue_sz*4);                             //Number of bytes in the queue
    
    return queue_def->controlblock;
}

/**
* @brief Put a Message to a Queue.
* @param  queue_id  message queue ID obtained with \ref osMessageCreate.
* @param  info      message information.
* @param  millisec  timeout value or 0 in case of no time-out.
* @retval status code that indicates the execution status of the function.
* @note   MUST REMAIN UNCHANGED: \b osMessagePut shall be consistent in every CMSIS-RTOS.
*/
osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec)
{
    ULONG sbuff[4];
    
    sbuff[0] = info;
    
    tx_queue_send(queue_id,  sbuff ,millisec);
    
    return osOK;
}

/**
* @brief Get a Message or Wait for a Message from a Queue.
* @param  queue_id  message queue ID obtained with \ref osMessageCreate.
* @param  millisec  timeout value or 0 in case of no time-out.
* @retval event information that includes status code.
* @note   MUST REMAIN UNCHANGED: \b osMessageGet shall be consistent in every CMSIS-RTOS.
*/
osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec)
{
    UINT os_err;
    ULONG rbuff[4];
    osEvent res;
        
    os_err = tx_queue_receive(queue_id,  rbuff ,millisec);
    
    if(os_err == TX_SUCCESS)
    {
        res.value.v = rbuff[0];
        res.status = osOK;
        res.def.message_id = queue_id;
    }
    else
    {
        res.value.v = 0;
        res.status = osErrorTimeoutResource;
        res.def.message_id = queue_id; 
    }
    
    return res;
}




/// Create and Initialize a Semaphore object used for managing resources.
/// \param[in]     semaphore_def semaphore definition referenced with \ref osSemaphore.
/// \param[in]     count         number of available resources.
/// \return semaphore ID for reference by other functions or NULL in case of error.
/// \note MUST REMAIN UNCHANGED: \b osSemaphoreCreate shall be consistent in every CMSIS-RTOS.
osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count)
{
    UINT os_err;
    
    os_err = tx_semaphore_create(
        semaphore_def->controlblock,
        semaphore_def->name,
        count);

    if(os_err == TX_SUCCESS)
    {
        return semaphore_def->controlblock;
    }

    return 0;
}

/// Wait until a Semaphore token becomes available.
/// \param[in]     semaphore_id  semaphore object referenced with \ref osSemaphoreCreate.
/// \param[in]     millisec      timeout value or 0 in case of no time-out.
/// \return number of available tokens, or -1 in case of incorrect parameters.
/// \note MUST REMAIN UNCHANGED: \b osSemaphoreWait shall be consistent in every CMSIS-RTOS.
int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec)
{
    UINT os_err;
    
    os_err =tx_semaphore_get(
        semaphore_id,
        millisec);
    
    if(os_err == TX_SUCCESS)
    {
        return semaphore_id->tx_semaphore_count;
    }

    return 0;
}

/// Release a Semaphore token.
/// \param[in]     semaphore_id  semaphore object referenced with \ref osSemaphoreCreate.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osSemaphoreRelease shall be consistent in every CMSIS-RTOS.
osStatus osSemaphoreRelease (osSemaphoreId semaphore_id)
    {
    UINT os_err;
    
    os_err =tx_semaphore_put(semaphore_id);
    
    if(os_err == TX_SUCCESS)
    {
        return osOK;
    }
    
    return osErrorParameter;
    }

/// Delete a Semaphore that was created by \ref osSemaphoreCreate.
/// \param[in]     semaphore_id  semaphore object referenced with \ref osSemaphoreCreate.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osSemaphoreDelete shall be consistent in every CMSIS-RTOS.
osStatus osSemaphoreDelete (osSemaphoreId semaphore_id)
        {
    UINT os_err;
    
    os_err =tx_semaphore_delete(semaphore_id);
    
    if(os_err == TX_SUCCESS)
    {
        return osOK;
    }
    
    return osErrorParameter;
}






/* USER CODE END Application */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
